<!DOCTYPE html>
<html>
 <head>
  <title>Quark combiner</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
  <link href="bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
  <link href='http://fonts.googleapis.com/css?family=Ubuntu+Mono&subset=latin,cyrillic,greek' rel='stylesheet' type='text/css'>
  <script type="text/javascript" src="html5slider.js"></script>
  <style type="text/css">
	div table {
		font-family: 'Ubuntu Mono', 'Courier New', monospace;
	}
  </style>
 </head>
<body>
 <div class="container">
  <div class="row">
   <div class="span12"><h2>Forth Quark combiner</h2></div>
   <div class="span4">
    <button class="btn" onclick="drom.render(100)">Report 100 &gt;</button>
    <button class="btn" onclick="drom.render(10000)">Report 10000 &gt;</button>
    <form name="form">
     <legend>Resource limitations</legend>
     <label class="checkbox"><input name="branch" type="checkbox">Single branch in last slot</label>
     <label class="checkbox"><input name="loadstore" type="checkbox">Single Load/Store unit</label>

     <div><input type="range" min="0" max="6" value="6" step="1" onchange="drom.showValue(this.value, 'lit_slots')"/> : <span id='lit_slots'>6</span> LIT slots</div>
     <div><input type="range" min="0" max="6" value="6" step="1" onchange="drom.showValue(this.value, 'alu')"/> : <span id='alu'>6</span> ALUs</div>
     <div><input type="range" min="0" max="6" value="6" step="1" onchange="drom.showValue(this.value, 'ps_push')"/> : <span id='ps_push'>6</span> PS push limit</div>
     <div><input type="range" min="0" max="6" value="6" step="1" onchange="drom.showValue(this.value, 'ps_pop' )"/> : <span id='ps_pop'>6</span> PS pop limit</div>
     <div><input type="range" min="0" max="6" value="6" step="1" onchange="drom.showValue(this.value, 'rs_push')"/> : <span id='rs_push'>6</span> RS push limit</div>
     <div><input type="range" min="0" max="6" value="6" step="1" onchange="drom.showValue(this.value, 'rs_pop' )"/> : <span id='rs_pop'>6</span> RS pop limit</div>

     <legend>Useless combinations</legend>
     <label class="checkbox"><input name="dropfear" type="checkbox">Remove (ALU DUP ...) DROP</label>
     <label class="checkbox"><input name="r2r"      type="checkbox">Remove R> >R, >R R></label>
     <label class="checkbox"><input name="litalu1"  type="checkbox">Remove LIT ALU1</label>
    </form>
   </div>
   <div class="span8">
    <div class="tabbable">
    <ul class="nav nav-tabs">
     <li class="active"><a href="#tab1" data-toggle="tab" id="lab1">1</a></li>
     <li><a href="#tab2" data-toggle="tab" id="lab2">2</a></li>
     <li><a href="#tab3" data-toggle="tab" id="lab3">3</a></li>
     <li><a href="#tab4" data-toggle="tab" id="lab4">4</a></li>
     <li><a href="#tab5" data-toggle="tab" id="lab5">5</a></li>
    </ul>
    <div class="tab-content">
     <div class="tab-pane active" id="tab1">
      <table class="table table-hover">
       <thead><tr><th>word</th><th>PS</th><th>RS</th></tr></thead>
       <tbody id="tbody1"></tbody>
      </table>
     </div>
     <div class="tab-pane" id="tab2">
      <table class="table table-hover">
       <thead><tr><th>phrase</th><th>PS</th><th>RS</th></tr></thead>
       <tbody id="tbody2"></tbody>
     </table>
     </div>
     <div class="tab-pane" id="tab3">
      <table class="table table-hover">
       <thead><tr><th>phrase</th><th>PS</th><th>RS</th></tr></thead>
       <tbody id="tbody3"></tbody>
      </table>
     </div>
     <div class="tab-pane" id="tab4">
      <table class="table table-hover">
       <thead><tr><th>phrase</th><th>PS</th><th>RS</th></tr></thead>
       <tbody id="tbody4"></tbody>
      </table>
     </div>
     <div class="tab-pane" id="tab5">
      <table class="table table-hover">
       <thead><tr><th>phrase</th><th>PS</th><th>RS</th></tr></thead>
       <tbody id="tbody5"></tbody>
      </table>
     </div>
    </div>
   </div>
  </div>
 </div>
 <script src="http://code.jquery.com/jquery.js"></script>
 <script src="bootstrap/js/bootstrap.min.js"></script>
 <script type="text/javascript">
	var drom = drom || {};
	(function () {
		"use strict";
		drom.words = [ // branch(0) loadstore(1) alu(2) drop-fear(3) lit_slot(4)    PS-stack-change(5) RS-stack-change(6)
			{name:'BRANCH',      use:[1, 0, 0, 1, 0,  -1, 0,     1, 0]}, // (     addr --   )
			{name:'?BRANCH',     use:[1, 0, 0, 1, 0,  -1, 0,     2, 0]}, // (   x addr -- x )
			{name:'NEXT',        use:[1, 0, 0, 1, 0,  -1, 0,     1, 0]}, // (     addr --   | x -- z )
			{name:'LIT8',        use:[0, 0, 0, 1, 1,   1, 0,    -1, 0]}, // (          -- x )
			{name:'LIT16',       use:[0, 0, 0, 1, 1,   1, 0,    -1, 0]}, // (          -- x )
			{name:'LIT32',       use:[0, 0, 0, 1, 1,   1, 0,    -1, 0]}, // (          -- x )
			{name:'ALU1',        use:[0, 0, 1, 1, 1,   0, 0,     0, 0]}, // (        x -- z )
			{name:'ALU2',        use:[0, 0, 1, 1, 1,  -1, 0,     1, 0]}, // (      x y -- z )
			{name:'@',           use:[0, 1, 0, 1, 0,   0, 0,     0, 0]}, // (     addr -- val )
			{name:'OVER_SWAP_!', use:[0, 1, 0, 0, 0,  -1, 0,     2, 0]}, // ( val addr -- val )
			{name:'>R',          use:[0, 0, 0, 0, 0,  -1, 1,     1,-1]}, // (        x --   |   -- x )
			{name:'R>',          use:[0, 0, 0, 0, 0,   1,-1,    -1, 1]}, // (          -- x | x --   )
			{name:'DUP',         use:[0, 0, 0, 1, 0,   1, 0,     0, 0]}, // (        x -- x x )
			{name:'OVER',        use:[0, 0, 0, 1, 0,   1, 0,     0, 0]}, // (      x y -- x y x )
			{name:'DROP',        use:[0, 0, 0, 0, 0,  -1, 0,     1, 0]}, // (        x --   )
		];
		drom.showValue = function (newValue, where) { document.getElementById(where).innerHTML = newValue; }
		function good_loadstore (arr) {
			"use strict";
			if (!document.form.loadstore.checked) { return 1; }
			var i, count = 0;
			for (i = 0; i < arr.length; i++) {
				count += drom.words[arr[i]].use[1]; // loadstore
			}
			if (count > 1) { return 0; }
			return 1;
		}
		function good_alu (arr) {
			"use strict";
			var i, count = 0;
			for (i = 0; i < arr.length; i++) {
				count += drom.words[arr[i]].use[2]; // ALUs
			}
			if (count > Number(document.getElementById('alu').innerHTML)) { return 0; }
			return 1;
		}
		function good_dropfear (arr) {
			"use strict";
			if (!document.form.dropfear.checked) { return 1; }
			var i;
			for (i = 1; i < arr.length; i++) {
				if ((drom.words[arr[i]].name === 'DROP') && (drom.words[arr[i-1]].use[3])) { return 0; } // drop fear
			}
			return 1;
		}
		function good_lit_slot (arr) {
			"use strict";
			var i, count = 0;
			for (i = 0; i < arr.length; i++) {
				count += drom.words[arr[i]].use[4]; // LIT slots
			}
			if (count > Number(document.getElementById('lit_slots').innerHTML)) { return 0; }
			return 1;
		}
		function good_r2r (arr) {
			"use strict";
			if (!document.form.r2r.checked) { return 1; }
			var i;
			for (i = 1; i < arr.length; i++) {
				if ((drom.words[arr[i]].name === 'R>') && (drom.words[arr[i-1]].name === '>R')) { return 0; }
				if ((drom.words[arr[i]].name === '>R') && (drom.words[arr[i-1]].name === 'R>')) { return 0; }
			}
			return 1;
		}
		function good_litalu1 (arr) {
			"use strict";
			if (!document.form.litalu1.checked) { return 1; }
			var i;
			for (i = 1; i < arr.length; i++) {
				if ((drom.words[arr[i]].name === 'ALU1') && (drom.words[arr[i-1]].name === 'LIT')) { return 0; }
			}
			return 1;
		}
		function good_balance (arr) {
			"use strict";
			var i, count;
			count = 0;
			for (i = 0; i < arr.length; i++) {
				count += drom.words[arr[i]].use[5]; // PS balance
			}
			if (count >  Number(document.getElementById('ps_push').innerHTML)) { return 0; }
			if (count < -Number(document.getElementById('ps_pop').innerHTML)) { return 0; }
			count = 0;
			for (i = 0; i < arr.length; i++) {
				count += drom.words[arr[i]].use[6]; // RS balance
			}
			if (count >  Number(document.getElementById('rs_push').innerHTML)) { return 0; }
			if (count < -Number(document.getElementById('rs_pop').innerHTML)) { return 0; }
			return 1;
		}
		function good_to_go (arr) {
			"use strict";
			if (!good_alu(arr)) { return 0; }
			if (!good_loadstore(arr)) { return 0; }
			if (!good_dropfear(arr)) { return 0; }
			if (!good_r2r(arr)) { return 0; }
			if (!good_litalu1(arr)) { return 0; }
			if (!good_balance(arr)) { return 0; }
			if (!good_lit_slot(arr)) { return 0; }
			return 1;
		}
		function print_row (arr) {
			"use strict";
			var i, ret, count;
			ret = '<tr><td>';
			for (i = 0; i < arr.length; i++) {
				ret += drom.words[arr[i]].name + ' ';
			}
			ret += '</td><td>';
			count = 0;
			for (i = 0; i < arr.length; i++) {
				count += drom.words[arr[i]].use[5];
			}
			ret += count + '</td><td>';
			count = 0;
			for (i = 0; i < arr.length; i++) {
				count += drom.words[arr[i]].use[6];
			}
			ret += count + '</td>';
			return ret;
		}
		function run1 () {
			"use strict";
			var i, count = 0, ret = '';
			for (i = 0; i < drom.words.length; i++) {
				if (good_to_go([i])) {
					ret += print_row([i]);
					count += 1;
				}
			}
			document.getElementById('tbody1').innerHTML = ret;
			document.getElementById('lab1').innerHTML = '1 (' + count + ')';
		};
		function run2 () {
			"use strict";
			var i0, i1, count = 0, branch, ret = '';
			branch = document.form.branch.checked;
			for (i0 = 0; i0 < drom.words.length; i0++) {
				if (!(branch && (drom.words[i0].use[0]))) { // branch slot
				for (i1 = 0; i1 < drom.words.length; i1++) {
					if (good_to_go([i0, i1])) {
						ret += print_row([i0, i1]);
						count += 1;
					}
				}}
			}
			document.getElementById('tbody2').innerHTML = ret;
			document.getElementById('lab2').innerHTML = '2 (' + count + ')';
		};
		function run3 (reports) {
			"use strict";
			var i0, i1, i2, count = 0, branch, ret = '';
			branch = document.form.branch.checked;
			for (i0 = 0; i0 < drom.words.length; i0++) {
				if (!(branch && (drom.words[i0].use[0]))) { // branch slot
				for (i1 = 0; i1 < drom.words.length; i1++) {
					if (!(branch && (drom.words[i1].use[0]))) { // branch slot
					for (i2 = 0; i2 < drom.words.length; i2++) {
						if (good_to_go([i0, i1, i2])) {
							if (count < reports) { ret += print_row([i0, i1, i2]); }
							count += 1;
						}
					}}
				}}
			}
			document.getElementById('tbody3').innerHTML = ret;
			document.getElementById('lab3').innerHTML = '3 (' + count + ')';
		};
		function run4 (reports) {
			"use strict";
			var i0, i1, i2, i3, count = 0, branch, ret = '';
			branch = document.form.branch.checked;
			for (i0 = 0; i0 < drom.words.length; i0++) {
				if (!(branch && (drom.words[i0].use[0]))) { // branch slot
				for (i1 = 0; i1 < drom.words.length; i1++) {
					if (!(branch && (drom.words[i1].use[0]))) { // branch slot
					for (i2 = 0; i2 < drom.words.length; i2++) {
						if (!(branch && (drom.words[i2].use[0]))) { // branch slot
						for (i3 = 0; i3 < drom.words.length; i3++) {
							if (good_to_go([i0, i1, i2, i3])) {
								if (count < reports) { ret += print_row([i0, i1, i2, i3]); }
								if (count > 1000000) {
									document.getElementById('tbody4').innerHTML = ret;
									document.getElementById('lab4').innerHTML = '4 (>1M)';
									return 0;
								}
								count += 1;
							}
						}}
					}}
				}}
			}
			document.getElementById('tbody4').innerHTML = ret;
			document.getElementById('lab4').innerHTML = '4 (' + count + ')';
		};
		function run5 (reports) {
			"use strict";
			var i0, i1, i2, i3, i4, count = 0, branch, ret = '';
			branch = document.form.branch.checked;
			for (i0 = 0; i0 < drom.words.length; i0++) {
				if (!(branch && (drom.words[i0].use[0]))) { // branch slot
				for (i1 = 0; i1 < drom.words.length; i1++) {
					if (!(branch && (drom.words[i1].use[0]))) { // branch slot
					for (i2 = 0; i2 < drom.words.length; i2++) {
						if (!(branch && (drom.words[i2].use[0]))) { // branch slot
						for (i3 = 0; i3 < drom.words.length; i3++) {
							if (!(branch && (drom.words[i3].use[0]))) { // branch slot
							for (i4 = 0; i4 < drom.words.length; i4++) {
								if (good_to_go([i0, i1, i2, i3, i4])) {
									if (count < reports) { ret += print_row([i0, i1, i2, i3, i4]); }
									if (count > 1000000) {
										document.getElementById('tbody5').innerHTML = ret;
										document.getElementById('lab5').innerHTML = '5 (>1M)';
										return;
									}
									count += 1;
								}
							}}
						}}
					}}
				}}
			}
			document.getElementById('tbody5').innerHTML = ret;
			document.getElementById('lab5').innerHTML = '5 (' + count + ')';
		};
		drom.render = function (reports) {
			"use strict";
			console.time('main');
			run1();
			run2();
			run3(reports);
			run4(reports);
			run5(reports);
			console.timeEnd('main');
		};
	})();
 </script>
<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-27923568-1']);
  _gaq.push(['_setDomainName', 'stackdrom.googlecode.com']);
  _gaq.push(['_setAllowLinker', true]);
  _gaq.push(['_trackPageview']);
  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'stats.g.doubleclick.net/dc.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
</script>
</body>
</html>
